package com.example.demo.api;

import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.Optional;

/**
 * 接口数据返回统一格式
 *
 * @author Shanks
 * @date 2020-03-28
 */
@Data
@Accessors(chain = true)
public class R<T> implements Serializable {

    private static final long serialVersionUID = -5609762060612631318L;

    private int code;
    private String message;
    private T data;

    public R(ErrorCode errorCode) {
        errorCode = Optional.ofNullable(errorCode).orElse(ApiErrorCode.ERROR);
        this.code = errorCode.getCode();
        this.message = errorCode.getMessage();
    }

    public static R success() {
        return success(null);
    }

    public static <T> R<T> success(T data) {
        ApiErrorCode apiErrorCode = ApiErrorCode.SUCCESS;
        if (data instanceof Boolean && Boolean.FALSE.equals(data)) {
            apiErrorCode = ApiErrorCode.ERROR;
        }
        return restResult(data, apiErrorCode);
    }

    public static <T> R<T> error(String message) {
        return restResult(null, ApiErrorCode.ERROR.getCode(), message);
    }

    public static <T> R<T> error(int code, String message) {
        return restResult(null, code, message);
    }

    public static <T> R<T> error(ErrorCode errorCode) {
        return restResult(null, errorCode);
    }

    public static <T> R<T> restResult(T data, ErrorCode errorCode) {
        return restResult(data, errorCode.getCode(), errorCode.getMessage());
    }

    private static <T> R<T> restResult(T data, int code, String message) {
        R<T> result = new R<>();
        result.setCode(code);
        result.setMessage(message);
        result.setData(data);
        return result;
    }

    public boolean ok() {
        return ApiErrorCode.SUCCESS.getCode() == code;
    }

    /**
     * 服务间调用非业务正常, 异常直接释放
     */
    public T serviceData() {
        if (!ok()) {
            throw new ApiException(this.message);
        }
        return data;
    }

    private R() {}
}